package smlab.view.ui.list
{
	import flash.display.InteractiveObject;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	
	[Event(name="item_change",type="smlab.view.ui.list.ListEvent_SM")]
	/**
	 * ITEM_CLICK 事件只是表明有列表项被点击了，要获取哪一项的数据被点击请用 ITEM_CHANGE
	 */
	[Event(name="item_click",type="smlab.view.ui.list.ListEvent_SM")]
	[Event(name="item_double_click",type="smlab.view.ui.list.ListEvent_SM")]
	[Event(name="item_roll_out",type="smlab.view.ui.list.ListEvent_SM")]
	[Event(name="item_roll_over",type="smlab.view.ui.list.ListEvent_SM")]
	
	/**
	 * 列表组件
	 * @author simon
	 * date:2010.2.11
	 * update:2010.2.21
	 * 
	 */
	public class List_SM extends Sprite implements IList_SM
	{
		private var _itemClass:Class;
		private var _rowNum:uint;//行数
		private var _rowGap:Number;
		private var _columnNum:uint;//列数
		private var _columnGap:Number;
		private var _itemWidth:Number;
		private var _itemHeight:Number;
		
		private var _allowMultiSelect:Boolean=false;
		protected var _dataProvider:Array=[];
		private var _items:Array=[];//所有项
		private var _itemsContainer:Sprite;//所有项的容器
		protected var _selectedItem:IListItem_SM;
		protected var _selectedData:Object;
		protected var _selectable:Boolean=true;
		protected var _selectedIndex:int;
		protected var _selectedItems:Array=[];
		protected var _selectedDatas:Array=[];
		public var stopEventWhenMouseDown:Boolean = true;//当 Item 被点击时是否阻止事件冒泡（防止鼠标事件穿越 list，导致其它对象响应鼠标事件）
		
		/**
		 * 构造函数
		 * @param itemClass		必须是继承于 ListItem_SM 的类
		 * @param rowNum		行数(值为0代表根据设置的 dataProvider 自动产生行，注意：行数和列数不能同时为0)
		 * @param rowGap		行距
		 * @param columnNum		列数(值为0代表根据设置的 dataProvider 自动产生列，注意：行数和列数不能同时为0)
		 * @param columnGap		列距
		 * @param itemWidth		强制规定 Item 的计算宽度（不会改变item实际宽度的）
		 * @param itemHeight	强制规定 Item 的计算高度（不会改变item实际高度的）
		 * 
		 */
		public function List_SM(itemClass:Class,rowNum:uint=0,rowGap:Number=0,columnNum:uint=1,columnGap:Number=0,itemWidth:Number = 0,itemHeight:Number = 0)
		{
			super();
			_itemClass=itemClass;
			_rowNum=rowNum;
			_rowGap=rowGap;
			_columnNum=columnNum;
			_columnGap=columnGap;
			_itemWidth = itemWidth;
			_itemHeight = itemHeight;
			_itemsContainer=new Sprite;
			addChild(_itemsContainer);
		}
		
		public function set allowMultiSelect(value:Boolean):void
		{
			_allowMultiSelect=value;
		}
		
		public function get allowMultiSelect():Boolean
		{
			return _allowMultiSelect;
		}
		
		public function set dataProvider(value:Array):void
		{
			removeAll();
			_dataProvider=value;
			update();
		}
		
		public function get dataProvider():Array
		{
			return _dataProvider;
		}
		
		private function update():void
		{
			var n:int=_dataProvider.length;
			
			while(_itemsContainer.numChildren>0){
				_itemsContainer.removeChildAt(0);
			}
			
			if(n==0){
				return;
			}
			
			var columnNumTemp:uint = _columnNum;
			var rowNumTemp:uint = _rowNum;
			
			if(_columnNum==0){
				columnNumTemp=int(n/rowNumTemp)+ (n%rowNumTemp>0 ? 1 : 0);
			}
			
			if(_rowNum==0){
				rowNumTemp=int(n/columnNumTemp)+ (n%columnNumTemp>0 ? 1 : 0);
			}
			
			if(columnNumTemp==0 || rowNumTemp==0){
				return;
			}
			
			for(var i:int=0;i<n;i++)
			{
				var item:InteractiveObject=InteractiveObject(new _itemClass);
				IListItem_SM(item).index=i;
				IListItem_SM(item).data=_dataProvider[i];
				
				if(_itemWidth == 0){
					_itemWidth = item.width;
				}
				
				if(_itemHeight == 0){
					_itemHeight = item.height;
				}
				
				//由行列数计算坐标
				var $x:Number=(i%columnNumTemp)*(_itemWidth + _columnGap);
				var $y:Number=int(i/columnNumTemp)*(_itemHeight + _rowGap);
				item.x=$x;
				item.y=$y;
				
				item.doubleClickEnabled=true;
				item.addEventListener(MouseEvent.DOUBLE_CLICK,itemMouseHandler);
				item.addEventListener(MouseEvent.CLICK,itemMouseHandler);
				item.addEventListener(MouseEvent.MOUSE_DOWN,itemMouseHandler);
				item.addEventListener(MouseEvent.ROLL_OUT,itemMouseHandler);
				item.addEventListener(MouseEvent.ROLL_OVER,itemMouseHandler);
				_itemsContainer.addChild(item);
				_items.push(item);
			} 
		}
		
		/**
		 * item 的鼠标事件
		 * @param e
		 * 
		 */
		private function itemMouseHandler(e:MouseEvent):void
		{
			var item:IListItem_SM=IListItem_SM(e.currentTarget);
			
			switch(e.type)
			{
				case MouseEvent.CLICK:
					this.dispatchEvent(new ListEvent_SM(ListEvent_SM.ITEM_CLICK));
					if(!_selectable)
					{
						return;
					}
					move(item.index);
				break;
				case MouseEvent.MOUSE_DOWN:
					if(stopEventWhenMouseDown)
					{
						e.stopImmediatePropagation();
					}
					
					if(!_selectable)
					{
						return;
					}
				break;
				case MouseEvent.DOUBLE_CLICK:
					this.dispatchEvent(new ListEvent_SM(ListEvent_SM.ITEM_DOUBLE_CLICK));
					if(!_selectable)
					{
						return;
					}
					move(item.index);
				break;
				case MouseEvent.ROLL_OVER:
					this.dispatchEvent(new ListEvent_SM(ListEvent_SM.ITEM_ROLL_OVER));
				break;
				case MouseEvent.ROLL_OUT:
					this.dispatchEvent(new ListEvent_SM(ListEvent_SM.ITEM_ROLL_OUT));
				break;
			}
			
		}
		
		public function get selectedItem():IListItem_SM
		{
			return _selectedItem;
		}
		
		public function get selectedData():Object
		{
			return _selectedData;
		}
		
		public function set selectable(value:Boolean):void
		{
			_selectable=value;
		}
		
		public function get selectable():Boolean
		{
			return _selectable;
		}
		
		public function get selectedIndex():int
		{
			return _selectedIndex;
		}
		
		public function get selectedItems():Array
		{
			return _selectedItems;
			//todo
		}
		
		public function get selectedDatas():Array
		{
			return _selectedDatas;
			//todo
		}
		
		/**
		 * 这里要求插入的是数据项而不是 ListItem_SM 的实例
		 * @param item
		 * 
		 */
		public function addItem(item:IListItem_SM):void
		{
			_dataProvider.push(item.data);
			dataProvider=_dataProvider;			
		}
		
		/**
		 * 这里要求插入的是数据项而不是 ListItem_SM 的实例
		 * @param item	数据项
		 * @param index	索引从0开始
		 * 
		 */
		public function addItemAt(item:IListItem_SM, index:uint):void
		{
			_dataProvider.splice(index,0,item.data);
			dataProvider=_dataProvider;
		}
		
		/**
		 * 这里返回的是 item(IListItem_SM) 而不是数据项
		 * @param index
		 * @return 
		 * 
		 */
		public function getItemAt(index:uint):IListItem_SM
		{
			return _items[index];
		}
		
		/**
		 * 这里返回的是 item(IListItem_SM) 而不是数据项
		 * @param item
		 * @param index
		 * @return 
		 * 
		 */
		public function replaceItemAt(item:IListItem_SM, index:uint):IListItem_SM
		{
			itemDoRemove(index);
			
			_dataProvider.splice(index,1);
			_dataProvider.splice(index,0,item.data);
			dataProvider=_dataProvider;
			return _items[index];
		}
		
		/**
		 * /移动到（选中）某项，负值代表不选择任何项
		 * @param index
		 * 
		 */
		public function move(index:int):void
		{
			if(_selectedItem!=null){
				_selectedItem.selected=false;
			}
			
			if(index<0 || index>=_dataProvider.length){
				_selectedItem=null;
				_selectedData=null;
				_selectedIndex=index;
			}else{
				var item:IListItem_SM=_items[index];
				_selectedIndex=item.index;
				_selectedData=item.data;
				_selectedItem=item;
				item.selected=true;
			}
			
			this.dispatchEvent(new ListEvent_SM(ListEvent_SM.ITEM_CHANGE));
		}
		
		public function removeAll():void
		{
			_dataProvider=[];
			//dataProvider=_dataProvider;
			
			itemAllDoRemove();
			
			if(_items){
				_items = [];
			}
		}
		
		private function itemAllDoRemove():void
		{
			if(_items){
				if(_items.length>0){
					for(var i:int=0;i<_items.length;i++){
						ListItem_SM(_items[i]).remove();
					}
				}
			}
		}
		
		private function itemDoRemove(index:int):void
		{
			var it:IListItem_SM=_items[index];
			
			if(it){
				it.remove();
			}
		}
		
		public function removeItem(item:IListItem_SM):IListItem_SM
		{
			var obj:IListItem_SM;
			
			for(var i:int=0;i<_dataProvider.length;i++){
				var tmp:IListItem_SM;
				tmp=_items[i];
				if(tmp==item){
					tmp.remove();
					_dataProvider.splice(tmp.index,1);
					obj=_items.splice(tmp.index,1)[0];
					dataProvider=_dataProvider;
					break;
				}
			}
			
			return obj;
		}
		
		public function removeItemAt(index:int):void
		{
			itemDoRemove(index);
			_dataProvider.splice(index,1);
			dataProvider=_dataProvider;
		}
		
	}
}